﻿using System;
using System.Data.SqlClient;
using System.Data;
using System.Threading;
using System.Collections;
using System.Configuration;

namespace Practico2.DataAccess
{

    public class TransactionManager
    {
        private static Hashtable _transactions = new Hashtable();
        
        private static object _syncTrn = new object();

        private static int CurrentThreadId
        {
            get { return Thread.CurrentThread.ManagedThreadId; }
        }

        public static void OpenTransaction()
        {
            IsolationLevel il = IsolationLevel.Unspecified;
            OpenTransaction(il);
        }

        public static void OpenTransaction(IsolationLevel il)
        {
            int threadId = CurrentThreadId;
            if (_transactions.ContainsKey(threadId))
            {
                throw new TransactionManagerException("thread already has a transaction");
            }

            SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["EBITAL_SGSO"].ConnectionString);
            connection.Open();

            SqlTransaction transaction = connection.BeginTransaction(il);
            _transactions.Add(threadId, transaction);
        }

        public static void CommitTransaction()
        {
            int threadId = CurrentThreadId;
            if (!_transactions.ContainsKey(threadId))
            {
                throw new TransactionManagerException("thread has not transaction");
            }
            SqlTransaction transaction = (SqlTransaction)_transactions[threadId];
            transaction.Commit();
            lock (_syncTrn)
            {
                _transactions.Remove(threadId);
            }
        }

        public static void RollbackTransaction()
        {
            int threadId = CurrentThreadId;
            if (!_transactions.ContainsKey(threadId))
            {
                throw new TransactionManagerException("thread has not transaction");
            }
            SqlTransaction transaction = (SqlTransaction)_transactions[threadId];
            lock (_syncTrn)
            {
                _transactions.Remove(threadId);
            }
            transaction.Rollback();
        }

        public static void DisposeTransaction()
        {
            int threadId = CurrentThreadId;
            if (_transactions.ContainsKey(threadId))
            {
                lock (_syncTrn)
                {
                    _transactions.Remove(threadId);
                }
                throw new TransactionManagerException("thread has pending transaction");
            }
        }

        public static SqlTransaction GetTransaction()
        {
            int threadId = CurrentThreadId;
            SqlTransaction toReturn = null;

            if (_transactions.ContainsKey(threadId))
            {
                toReturn = (SqlTransaction)_transactions[threadId];
            }

            return toReturn;
        }
        
        public class TransactionManagerException : ApplicationException
        {

            public TransactionManagerException(string message)
                : base(message)
            {
            }

        }
    }
}

